package edu.iu.criminfo.voronoi.kmeans;

import java.io.BufferedWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import edu.iu.criminfo.voronoi.cases.Case;
import edu.iu.criminfo.voronoi.object.Point;

public class Cluster {
	private Point prevCenter;
	private Point center;
	private List<Case> caseList;
	
	private double swCornerX;
	private double swCornerY;
	private double neCornerX;
	private double neCornerY;

	public Cluster(Point center) {
		this.center = center;
		this.prevCenter = new Point(center.coordinateX, center.coordinateY);
		this.caseList = new ArrayList<Case>();
	}

	public int clearAllCases() {
		caseList.clear();
		return caseList.size();
	}

	public int addCase(Case aCase) {
		caseList.add(aCase);
		return caseList.size();
	}
	
	public List<Case> getCaseList() {
		return caseList;
	}

	public void updateCenter() {

		prevCenter.coordinateX = center.coordinateX;
		prevCenter.coordinateY = center.coordinateY;

		int size = caseList.size();

		double coordinateX = 0;
		double coordinateY = 0;

		for (Case aCase : caseList) {
			coordinateX += aCase.getLocation().coordinateX;
			coordinateY += aCase.getLocation().coordinateY;
		}

		if (size > 0) {
			center.coordinateX = coordinateX / size;
			center.coordinateY = coordinateY / size;
		}
		caseList.clear();
	}

	public boolean isConverged(double threshold) {

		if (prevCenter.distance(center) < threshold) {
			return true;
		} else {

			return false;
		}

	}

	public Point getCenter() {
		return center;
	}

	public int size() {
		return caseList.size();
	}
	
	public void writeToWriter(BufferedWriter bufferedWriter) throws IOException {
		for (Case aCase: caseList) {
			bufferedWriter.write(aCase.getLocation().coordinateX + "\t" + aCase.getLocation().coordinateY);
			bufferedWriter.newLine();
		}
	}
	
	public void getBoundary() {
		swCornerX = caseList.get(0).getLocation().coordinateX;
		swCornerY = caseList.get(0).getLocation().coordinateY;
		neCornerX = swCornerX;
		neCornerY = swCornerY;
		
		for (Iterator<Case> it = caseList.iterator(); it.hasNext();) {
			Case aCase = it.next();
			Point point = aCase.getLocation();
			if (point.coordinateX < swCornerX) {
				swCornerX = point.coordinateX;
			} else if (point.coordinateX > neCornerX) {
				neCornerX = point.coordinateX;
			}
			if (point.coordinateY < swCornerY) {
				swCornerY = point.coordinateY;
			} else if (point.coordinateY > neCornerY) {
				neCornerY = point.coordinateY;
			}
		}
	}

	public double getSwCornerX() {
		return swCornerX;
	}

	public double getSwCornerY() {
		return swCornerY;
	}

	public double getNeCornerX() {
		return neCornerX;
	}

	public double getNeCornerY() {
		return neCornerY;
	}
}